package com.laker.admin.module.excel.facade.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.laker.admin.framework.constants.CodeTable;
import com.laker.admin.framework.model.Response;
import com.laker.admin.module.datasource.util.MssqlUtil;
import com.laker.admin.module.datasource.util.MysqlUtil;
import com.laker.admin.module.excel.application.ExcelDataApplication;
import com.laker.admin.module.excel.application.ExcelTemplateApplication;
import com.laker.admin.module.excel.domain.ExcelData;
import com.laker.admin.module.excel.domain.ExcelTemplate;
import com.laker.admin.module.excel.entity.ExcelDataCmd;
import com.laker.admin.module.excel.facade.ExcelDataFacade;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author nihongxin
 * @date 2021/12/14
 * @description
 */
@Service
public class ExcelDataFacadeImpl implements ExcelDataFacade {

    @Resource
    private ExcelDataApplication excelDataApplication;

    @Resource
    private ExcelTemplateApplication excelTemplateApplication;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Response save(ExcelDataCmd excelDataCmd) {
        try {
            Map<String, Object> map = (Map<String, Object>) JSON.parse(excelDataCmd.getExcelValue());
            String idString = MapUtils.getString(map, "rowId");
            List<String> fieldList = new ArrayList<>(10);
            if (!StringUtils.isEmpty(idString)) {
                if (idString.contains(",")) {
                    fieldList.addAll(Arrays.asList(idString.split(",")));
                } else {
                    fieldList.add(idString);
                }
            }

            List<Object> excelCoordinatesList = JSON.parseArray(excelDataCmd.getExcelCoordinatesList());
            for (int i = 0; i < excelCoordinatesList.size(); i++) {
                ExcelData excelDataCheck = excelDataApplication.getExcelDataByExcelTemplate(excelDataCmd, String.valueOf(excelCoordinatesList.get(i)));
                ExcelData excelData = new ExcelData();
                if (null != excelDataCheck) {
                    excelData.setId(excelDataCheck.getId());
                }
                excelData.setExcelTemplateId(excelDataCmd.getExcelTemplateId());
                excelData.setExcelTemplateSheetId(excelDataCmd.getExcelTemplateSheetId());
                excelData.setExcelCoordinates(String.valueOf(excelCoordinatesList.get(i)));
                excelData.setExcelValue(excelDataCmd.getExcelValue());
                excelData.setRowId(0L);
                if (!fieldList.isEmpty() && i < fieldList.size()) {
                    excelData.setRowId(Long.valueOf(fieldList.get(i)));
                }
                excelDataApplication.save(excelData);
            }
            return Response.ok();
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.error(e.getMessage());
        }
    }

    @Override
    public Response getExcelDataList(ExcelDataCmd excelDataCmd) {
        try {
            String coord = "";
            List<Object> excelCoordinatesList = JSON.parseArray(excelDataCmd.getExcelCoordinatesList());
            List<String> excelCoordinatesStringList = excelCoordinatesList.stream().map(o -> String.valueOf(o)).collect(Collectors.toList());
            if (!excelCoordinatesStringList.isEmpty()) {
                coord = excelCoordinatesStringList.get(0);
            }
            List<ExcelData> excelDataList = excelDataApplication.getExcelDataList(excelDataCmd);
            for (ExcelData excelData : excelDataList) {
                Map<String, Object> map = (Map<String, Object>) JSON.parse(excelData.getExcelValue());
                String rangeFullString = MapUtils.getString(map, "rangeFull");
                List<String> rangeFullList = JSONArray.parseArray(rangeFullString, String.class);
                String idString = MapUtils.getString(map, "rowId");
                if (!StringUtils.isEmpty(idString)) {
                    List<String> fieldList = new ArrayList<>(10);
                    if (!StringUtils.isEmpty(idString)) {
                        if (idString.contains(",")) {
                            fieldList.addAll(Arrays.asList(idString.split(",")));
                        } else {
                            fieldList.add(idString);
                        }
                    }
                    String rowId = "";
                    for (int i = 0; i < rangeFullList.size(); i++) {
                        if (coord.equals(rangeFullList.get(i))) {
                            rowId = fieldList.get(i);
                        }
                    }
                    map.put("rowId", rowId);
                    excelData.setExcelValue(String.valueOf(map));
                }
            }
            return Response.ok(excelDataList);
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }

    @Override
    public Response saveExcelData(ExcelDataCmd excelDataCmd) {
        try {
            List<Object> excelCoordinatesList = JSON.parseArray(excelDataCmd.getExcelCoordinatesList());
            ExcelData excelData = new ExcelData();
            excelData.setId(excelDataCmd.getId());
            excelData.setExcelTemplateId(excelDataCmd.getExcelTemplateId());
            excelData.setExcelTemplateSheetId(excelDataCmd.getExcelTemplateSheetId());
            excelData.setExcelCoordinates(String.valueOf(excelCoordinatesList.get(0)));
            excelData.setExcelValue(excelDataCmd.getExcelValue());
            return Response.ok(excelDataApplication.save(excelData));
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }

/*    @Override
    public Response getByTemplateId(Long excelTemplateId) {
        try {
            List<ExcelData> excelDataList = excelDataApplication.getExcelDataListByExcelTemplateId(excelTemplateId);
            Map<String, Object> fileIdCoordMap = new HashMap<>(16);
            Set<String> fieldSet = new HashSet<>(10);
            Set<Long> idSet = new HashSet<>(10);
            List<String> idList = new ArrayList<>(10);
            Map<String, Set<Long>> fieldRowIdMap = new HashMap<>(16);
            String mysqlUrl = "";
            String username = "";
            String password = "";
            String mysqlDriver = CodeTable.MYSQL_DRIVER;
            String database = "";
            String tableName = "";
            for (ExcelData excelData : excelDataList) {
                Map<String, Object> map = (Map<String, Object>) JSON.parse(excelData.getExcelValue());
                String field = MapUtils.getString(map, "field");
                Map<String, Object> datasourceMap = (Map<String, Object>) MapUtils.getObject(map, "datasource");
                mysqlUrl = MapUtils.getString(datasourceMap, "dataSourceUrl");
                username = MapUtils.getString(datasourceMap, "username");
                password = MapUtils.getString(datasourceMap, "password");
                database = MapUtils.getString(map, "database");
                tableName = MapUtils.getString(map, "table");
                fieldSet.add(field);
                String idString = MapUtils.getString(map, "rowId");
                List<String> fieldList = new ArrayList<>(10);
                if (!StringUtils.isEmpty(idString)) {
                    if (idString.contains(",")) {
                        idList.addAll(Arrays.asList(idString.split(",")));
                        fieldList.addAll(Arrays.asList(idString.split(",")));
                    } else {
                        idList.add(idString);
                        fieldList.add(idString);
                    }
                }
                Set<Long> rowIdSet = new HashSet<>(10);
                fieldList.stream().forEach(x -> rowIdSet.add(Long.valueOf(x)));
                fieldRowIdMap.put(field, rowIdSet);
            }
            idList.stream().forEach(x -> idSet.add(Long.valueOf(x)));
            for (String fieldStr : fieldSet) {
                List<String> coordList = new ArrayList<>(10);
                int i = 0;
                for (ExcelData excelData : excelDataList) {
                    String excelCoordinates = excelData.getExcelCoordinates();
                    Map<String, Object> map = (Map<String, Object>) JSON.parse(excelData.getExcelValue());
                    String field = MapUtils.getString(map, "field");
                    if (fieldStr.equals(field)) {
                        coordList.add(i, excelCoordinates);
                        i++;
                    }
                }
                fileIdCoordMap.put(fieldStr, coordList);
            }
            ExcelTemplate excelTemplate = excelTemplateApplication.getById(excelTemplateId);
            List<Map<String, Object>> mapList = new ArrayList<>(10);
            if (CodeTable.SOURCE_TYPE_MYSQL == excelTemplate.getDataSource().getType()) {
                mapList = MysqlUtil.queryTableDataByFileIdCoordMap(mysqlUrl, username, password, mysqlDriver, database, tableName, fieldSet, fileIdCoordMap, idSet, fieldRowIdMap);
            } else {
                mapList = MssqlUtil.queryTableDataByFileIdCoordMap(mysqlUrl, username, password, mysqlDriver, database, tableName, fieldSet, fileIdCoordMap);
            }
            return Response.ok(mapList);
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }*/


    @Override
    public Response getByTemplateId(Long excelTemplateId) {
        try {
            List<ExcelData> excelDataList = excelDataApplication.getExcelDataListByExcelTemplateId(excelTemplateId);
            ExcelTemplate excelTemplate = excelTemplateApplication.getById(excelTemplateId);
            List<Map<String, Object>> mapAllList = new ArrayList<>(10);
            String mysqlDriver = CodeTable.MYSQL_DRIVER;
            Map<String, Integer> fieldIndex = new HashMap<>(16);
            for (ExcelData excelData : excelDataList) {
                List<Map<String, Object>> mapList = new ArrayList<>(10);
                Map<String, Object> map = (Map<String, Object>) JSON.parse(excelData.getExcelValue());
                String field = MapUtils.getString(map, "field");
                if (!fieldIndex.containsKey(field)) {
                    fieldIndex.put(field, 0);
                }
                Map<String, Object> datasourceMap = (Map<String, Object>) MapUtils.getObject(map, "datasource");
                String mysqlUrl = MapUtils.getString(datasourceMap, "dataSourceUrl");
                String username = MapUtils.getString(datasourceMap, "username");
                String password = MapUtils.getString(datasourceMap, "password");
                String database = MapUtils.getString(map, "database");
                String tableName = MapUtils.getString(map, "table");
                String excelCoordinates = excelData.getExcelCoordinates();
                Long rowId = excelData.getRowId();
                Integer indexInteger = MapUtils.getInteger(fieldIndex, field);
                if (CodeTable.SOURCE_TYPE_MYSQL == excelTemplate.getDataSource().getType()) {
                    mapList = MysqlUtil.queryTableDataByFileIdCoordMapNew(mysqlUrl, username, password, mysqlDriver, database, tableName, field, excelCoordinates, rowId, indexInteger);
                } else {
                    mapList = MssqlUtil.queryTableDataByFileIdCoordMap(mysqlUrl, username, password, mysqlDriver, database, tableName, field, excelCoordinates, rowId, indexInteger);
                }
                if (0L == rowId) {
                    indexInteger++;
                    fieldIndex.put(field, indexInteger);
                }
                mapAllList.addAll(mapList);
            }

            return Response.ok(mapAllList);
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
}
